<template>
  <el-dialog
    v-model="dialogVisible"
    class="detail-dialog-qvil"
    :close-on-click-modal="false"
    :title="title || '详情'"
    :width="width || '50%'"
    @close="handleClose"
  >
    <el-descriptions v-loading="isLoading" border class="detail-descriptions" :column="2">
      <el-descriptions-item
        v-for="field in visibleFields"
        :key="field.prop"
        class="descriptions-item"
        :label="field.label"
        :span="field.colSpan || 1"
      >
        <template v-if="field.render">
          {{ field.render(detailData[field.prop], detailData) }}
        </template>
        <template v-else>
          <span v-if="field.type === 'image'" class="empty-value">
            <el-image
              fit="cover"
              :src="getFieldValue(field, detailData)"
              style="width: 80px; height: 80px"
              @click="handlePreview(getFieldValue(field, detailData))"
            />
          </span>
          <span v-else-if="getFieldValue(field, detailData)">{{ getFieldValue(field, detailData) }}</span>

          <span v-else class="empty-value">暂无数据</span>
        </template>
      </el-descriptions-item>
    </el-descriptions>
    <el-image-viewer v-if="previewVisible" :url-list="previewSrcList" @close="previewVisible = false" />

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleClose">关闭</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'

// 定义Field接口
interface Field {
  prop: string
  label: string
  type?: string
  visible?: boolean
  colSpan?: number
  render?: (value: any, row: any) => any
  formatter?: (row: any) => any
}

// 定义props
const props = defineProps({
  modelValue: Boolean,
  title: String,
  width: [String, Number],
  loading: Boolean,
  fields: {
    type: Array as () => Field[],
    required: true,
  },
  detailData: {
    type: Object,
    default: () => ({}),
  },
})

const previewSrcList = ref<string[]>([])

const previewVisible = ref(false)
const handlePreview = (src: string) => {
  previewSrcList.value = [src]
  previewVisible.value = true
}

const emit = defineEmits(['update:modelValue', 'close'])

// 内部状态
const dialogVisible = ref(false)
const isLoading = ref(props.loading || false)

// 可见字段
const visibleFields = computed(() => {
  return props.fields.filter((field) => field.visible !== false)
})

// 监听外部 modelValue 变化
watch(
  () => props.modelValue,
  (val) => {
    if (val !== dialogVisible.value) {
      dialogVisible.value = val
    }
  },
  { immediate: true }
)

// 监听内部 dialogVisible 变化
watch(
  () => dialogVisible.value,
  (val) => {
    if (val !== props.modelValue) {
      emit('update:modelValue', val)
    }
  }
)

// 监听 loading 状态
watch(
  () => props.loading,
  (val) => {
    if (val !== undefined && val !== isLoading.value) {
      isLoading.value = val
    }
  }
)

// 获取字段值，支持formatter函数
const getFieldValue = (field: Field, data: any) => {
  const value = field.prop.includes('.') ? field.prop.split('.').reduce((obj: any, key: string) => obj && obj[key], data) : data[field.prop]

  return field.formatter ? field.formatter(data) : value
}

// 处理关闭
const handleClose = () => {
  dialogVisible.value = false
  emit('close')
}
</script>

<style scoped>
.detail-dialog-qvil :deep(.el-dialog) {
  overflow: hidden;
  border-radius: 12px;
}

.detail-dialog-qvil :deep(.el-dialog__header) {
  padding: 20px 20px 10px;
  margin: 0;
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.detail-dialog-qvil :deep(.el-dialog__title) {
  font-size: 18px;
  font-weight: 600;
}

.detail-dialog-qvil :deep(.el-dialog__body) {
  padding: 24px 24px 10px;
}

.detail-dialog-qvil :deep(.el-dialog__footer) {
  padding: 10px 24px 24px;
  border-top: none;
}

.detail-descriptions {
  width: 100%;
}

.detail-descriptions :deep(.el-descriptions__label) {
  min-width: 100px;
  padding: 12px 16px;
  font-weight: 500;
  white-space: nowrap;
  background-color: var(--el-fill-color-light);
}

.detail-descriptions :deep(.el-descriptions__content) {
  padding: 12px 16px;
}

.detail-descriptions :deep(.el-tag) {
  margin-right: 5px;
  margin-bottom: 5px;
}

.empty-value {
  font-size: 13px;
  color: var(--el-text-color-secondary);
}

.dialog-footer {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}
</style>
